#include <stdio.h>                                     //��׼�����������
#include <stdlib.h>                                    //��׼����ⶨ��
#include <unistd.h>                                    //Unix ��׼������
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>                                     //�ļ����ƶ���
#include <termios.h>                                   //PPSIX �ն˿��ƶ���
#include <errno.h>                                     //����Ŷ���
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stddef.h>
#include <sys/time.h>
#include <sys/ioctl.h>
int modem_handle;

unsigned long long time_usec()
{
    struct timeval tv;
    struct timezone tz;
//struct tm *tm;

    gettimeofday(&tv, &tz);
    /*tm =*/ //localtime(&tv.tv_sec);
    return (unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec;
}
int usleep_until(unsigned long long target_time)
{
    struct timeval tv;
    struct timezone tz;
    unsigned long long now;

    do
    {
        gettimeofday(&tv, &tz);
        now = (unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec;

//    if (terminate == 1)
//      return 1;

        if (now < target_time)
            usleep(100);
    }
    while (now < target_time);

    return 0;
}

// Read max characters from modem. The function returns when it received at
// least 1 character and then the modem is quiet for timeout*0.1s.
// The answer might contain already a string. In this case, the answer
// gets appended to this string.
int read_from_modem(char *answer , int max , int timeout)
{
    int count = 0;
    int got = 0;
    int timeoutcounter = 0;
    int success = 0;
    int toread = 0;

    do
    {
        // How many bytes do I want to read maximum? Not more than buffer size -1 for termination character.
        count = strlen(answer);
        toread = max - count - 1;
        if (toread <= 0)
            break;
        // read data
        got = read(modem_handle, answer + count, toread);
        // if nothing received ...
        if (got <= 0)
        {
            // wait a litte bit and then repeat this loop
            got = 0;
            usleep_until(time_usec() + 100000);
            timeoutcounter++;
        }
        else
        {
            // restart timout counter
            timeoutcounter = 0;
            // append a string termination character
            answer[count + got] = 0;
            success = 1;

            // 3.1.12: With Multitech network modem (telnet) there can be 0x00 inside the string:
            if (strlen(answer) < (size_t) count + got)
            {
                int i, j, len;

                len = count + got;
                j = 0;
                for (i = 0; i < count + got; i++)
                {
                    if (answer[i] == '\0')
                    {
                        len--;
                        continue;
                    }

                    if (i > j)
                        answer[j] = answer[i];
                    j++;
                }

                answer[len] = 0;
            }

        }
    }
    while (timeoutcounter < timeout);

//    // 3.1.12:
//    if (success && DEVICE_IS_SOCKET)
//    {
//        count += got;
//        negotiate_with_telnet(answer, &count);
//    }

    return success;
}

void setmodemparams()
{
  struct termios newtio;
  int baudrate;

  bzero(&newtio, sizeof(newtio));
  newtio.c_cflag = CS8 | CLOCAL | CREAD | O_NDELAY | O_NONBLOCK;
//  if (DEVICE.rtscts)
//    newtio.c_cflag |= CRTSCTS;
  newtio.c_iflag = IGNPAR;
  newtio.c_oflag = 0;
  newtio.c_lflag = 0;
  newtio.c_cc[VTIME] = 0;
  newtio.c_cc[VMIN] = 0;

//  baudrate = 115200;
  baudrate = B1152000;
  cfsetispeed(&newtio, baudrate);
  cfsetospeed(&newtio, baudrate);
  tcsetattr(modem_handle, TCSANOW, &newtio);
}


void printfile(char* file,char * pcTrace)
{
    /// 打印到文件
    FILE* fp = fopen(file, "wb");
    if (NULL != fp)
    {
        fputs(pcTrace, fp);
        fclose(fp);
    }else
    {
        fputs(pcTrace, stdout);
    }
}

/*                     argv[1]  argv[2] argv[3] argv[4]
 * Usage:putcommand </dev/ttyUSB2> <AT> <200> </home/out>
 *                  com端口       at命令 延时时间 输出地址，如果空则输出
 * */

int main(int argc , char*argv[])
{
    int len,time;
    char buf[4096];
    char command[1024];
    if (argv[1] == NULL || argv[2] == NULL || argv[3] == NULL)
    {
        return 0;
    }
    time = atoi(argv[3]);
    time /= 100;
    if ((modem_handle = open(argv[1], O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
    {
        sprintf(buf,"%s can't open\n",argv[1]);
        printfile(argv[4],buf);
        return -1;
    }
    setmodemparams();
    strcpy(command,argv[2]);
    char * p = strrchr(command, '\r');
    if(p == NULL)
       strcat(command, "\r");


    len = write(modem_handle, command, strlen(command));
    if (len < 0)
    {
        sprintf(buf,"%s can't write\n",argv[1]);
        printfile(argv[4],buf);
        return -1;
    }

    read_from_modem(buf , 4096 , time);
    printfile(argv[4],buf);
    close(modem_handle);
    return 0;
}
